package com.shopx.oss.service.impl;

//import com.aliyun.oss.OSSClient;
//import com.aliyun.oss.model.ObjectMetadata;
import com.shopx.base.exception.OriginException;
import com.shopx.core.common.CommonConstant;
import com.shopx.core.utils.DateTimeUtil;
import com.shopx.core.utils.FileUtil;
import com.shopx.core.utils.StringUtil;
import com.shopx.oss.service.IAliyunOssService;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Random;

/**
 * TODO
 *
 * @author:lituo
 * @date:2023/7/2
 **/
//@Service
@Slf4j
public class AliyunOssServiceImpl implements IAliyunOssService {
  /**
   * accessKeyId
   */
  @Value("${aliyun.accessKeyId}")
  private String accessKeyId;
  /**
   * accessKeySecret
   */
  @Value("${aliyun.accessKeySecret}")
  private String accessKeySecret;
  /**
   * 存储空间名称
   */
  @Value("${aliyun.oss.bucketName}")
  private String bucketName;
  /**
   * Endpoint（地域节点）
   */
  @Value("${aliyun.oss.endpoint}")
  private String endpoint;

  @Value("${aliyun.oss.domainApp}")
  private String domainApp;

  @Value("${aliyun.oss.rootFilePath}")
  private String rootFilePath;


  @Value("${file.imgSuffix}")
  private String imgSuffix;

  @Value("${file.workSuffix}")
  private String workSuffix;

  @Value("${file.cadSuffix}")
  private String cadSuffix;

  @Value("${file.maxNum.img}")
  private String imgMaxNum;

  @Value("${file.maxNum.work}")
  private String workMaxNum;

  @Value("${file.maxNum.cad}")
  private String cadMaxNum;


  @Value("${file.maxSize.img}")
  private String imgMaxSize;

  @Value("${file.maxSize.work}")
  private String workMaxSize;

  @Value("${file.maxSize.cad}")
  private String cadMaxSize;


  @Value("${file.oss.localPath}")
  private String localPath;

  @Value("${file.oss.filePrefix}")
  private String filePrefix;

  @Value("${file.oss.fileName}")
  private String fileName;

  @Value("${file.compress.scale}")
  private String scale;

  @Value("${file.compress.quality}")
  private String quality;

  @Value("${file.compress.limitSize}")
  private String limitSize;

  /*
   *	以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
   */
  private static final Integer ZERO = 0;
  private static final Integer ONE_ZERO_TWO_FOUR = 1024;
  private static final Integer NINE_ZERO_ZERO = 900;
  private static final Integer THREE_TWO_SEVEN_FIVE = 3275;
  private static final Integer TWO_ZERO_FOUR_SEVEN = 2047;
  private static final Double ZERO_EIGHT_FIVE = 0.85;
  private static final Double ZERO_SIX = 0.6;
  private static final Double ZERO_FOUR_FOUR = 0.44;
  private static final Double ZERO_FOUR = 0.4;

  @Override
  public String uploadFile(List<MultipartFile> list, String fileType, String cpId) throws Exception {
    String filePath = "";
    //验证文件格式
    checkFileSuffix(list, fileType);
    //验证一次文件上传数量
    checkFileNumber(list, fileType);
    //验证上传文件大小
    checkFileSize(list, fileType);
    //上传
    filePath = this.upload(list, fileType, cpId);
    return filePath.substring(0, filePath.length() - 1);
  }

  private String upload(List<MultipartFile> list, String fileType, String cpId) throws Exception {
//    log.info("upload.begin");
//    String curDt = DateTimeUtil.getDate8();
//    String filePath = rootFilePath + File.separator + cpId + File.separator + curDt;
//    if (CommonConstant.FileType.COREIMG.equals(fileType)) {
//      //核心文件
//      filePath = rootFilePath + File.separator + cpId + File.separator + "projFile" + File.separator + curDt;
//    } else if (CommonConstant.FileType.CAD.equals(fileType)) {
//      //cad文件
//      filePath = rootFilePath + File.separator + cpId + File.separator + "projCad" + File.separator + curDt;
//    }
//    String fileNames = "";
//    OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
//    for (MultipartFile file : list) {
////      String ext = FilenameUtils.getExtension(file.getOriginalFilename());
//      String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
//      String newName = "";
//      String origFileName = "";
//      if (!file.isEmpty()) {
//        byte[] bytes = file.getBytes();
//        Random random = new Random();
//        origFileName = String.valueOf(Math.abs(random.nextLong()));
//        newName = filePath + File.separator + origFileName + "." + ext;
//        //开始压缩
//        //如果小于100KB，不压缩。
//        double fileSize = (double) file.getSize() / 1048576;
//        if(!CommonConstant.FileType.CAD.equals(fileType) && fileSize>Double.valueOf(0.1)){
//          bytes = this.compressImage(file,fileType);
//        }
//        ObjectMetadata objectMetadata = new ObjectMetadata();
//        InputStream sbs = new ByteArrayInputStream(bytes);
//        objectMetadata.setContentLength(bytes.length);
//        objectMetadata.setContentType(file.getContentType());
//        //获取文件后缀名
//        objectMetadata.setCacheControl("no-cache");
//        objectMetadata.setHeader("Pragma", "no-cache");
//        if(CommonConstant.FileType.IMG.equals(fileType) || CommonConstant.FileType.COREIMG.equals(fileType)){
//          objectMetadata.setContentType("image/jpg");
//        }else{
//          objectMetadata.setContentType(file.getContentType());
//        }
//        objectMetadata.setContentDisposition("inline;filename=" + newName);
//        //上传文件
//        ossClient.putObject(bucketName, newName, sbs, objectMetadata);
//      } else {
//        log.error("上传文件为空");
//        throw new OriginException("99999", "上传文件为空");
//      }
//      fileNames +=  newName + ":" + origFileName + ",";
//    }
//    return fileNames;
    return null;
  }

  /**
   * @param fileType
   * @return byte[]
   * @desc 图片压缩
   * @author lituo
   * @date 2023/7/3 9:14 下午 @param file
   */
  public static byte[] compressImage(MultipartFile file, String fileType) {
    ByteArrayInputStream inputStream = null;
    ByteArrayOutputStream outputStream = null;
    try {
      inputStream = new ByteArrayInputStream(file.getBytes());
      outputStream = new ByteArrayOutputStream(file.getBytes().length);
      if (CommonConstant.FileType.COREIMG.equals(fileType)) {
        //核心文件
        double fileSize = (double) file.getSize() / 1048576;
        log.info("fileSize:{}", fileSize);
        if (fileSize > Double.valueOf(0.2)) {
          //大于1MB的图片，压缩50%
          log.info("COREIMG-90");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.9")).outputQuality(Float.valueOf("1")).toOutputStream(outputStream);
        }
        if (fileSize > Double.valueOf(1)) {
          log.info("COREIMG-50");
          //大于1MB的图片，压缩50%
          Thumbnails.of(inputStream).scale(Float.valueOf("0.8")).outputQuality(Float.valueOf("0.8")).toOutputStream(outputStream);
        } else if (fileSize > Double.valueOf(2)) {
          log.info("COREIMG-30");
          //大于2M，压缩到30%
          Thumbnails.of(inputStream).scale(Float.valueOf("0.5")).outputQuality(Float.valueOf("0.6")).toOutputStream(outputStream);
        } else if (fileSize > Double.valueOf(3)) {
          //大于3M，压缩到20%
          log.info("COREIMG-20");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.4")).outputQuality(Float.valueOf("0.5")).toOutputStream(outputStream);
        } else if (fileSize > Double.valueOf(4)) {
          //大于4M，压缩到10%
          log.info("COREIMG-10");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.3")).outputQuality(Float.valueOf("0.5")).toOutputStream(outputStream);
        }
      } else if (CommonConstant.FileType.IMG.equals(fileType)) {
        //非核心文件
        double fileSize = (double) file.getSize() / 1048576;
        if (fileSize > Double.valueOf(0)) {
          //大于1MB的图片，压缩50%
          log.info("IMG-30");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.5")).outputQuality(Float.valueOf("0.5")).toOutputStream(outputStream);
        } else if (fileSize > Double.valueOf(1)) {
          //大于1MB的图片，压缩50%
          log.info("IMG-20");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.4")).outputQuality(Float.valueOf("0.4")).toOutputStream(outputStream);
        } else if (fileSize > Double.valueOf(2)) {
          //大于4M，压缩到10%
          log.info("IMG-10");
          Thumbnails.of(inputStream).scale(Float.valueOf("0.2")).outputQuality(Float.valueOf("0.2")).toOutputStream(outputStream);
        }
      }
    } catch (Exception e) {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (Exception ex) {
          log.error("close.inputStream.error.",e);
        }
      }
      if (outputStream != null) {
        try {
          outputStream.close();
        } catch (Exception ex) {
          log.error("close.outputStream.error.",e);
        }
      }
    }
    return outputStream.toByteArray();
  }

  /**
   * 验证文件是否有效
   *
   * @param file（1：图片；2：文件；3：cad文件）
   * @param fileType
   * @return void
   * @author lituo
   * @date 5:38 PM 2021/12/12
   */
  private void checkFileSuffix(List<MultipartFile> file, String fileType) {
    String fileSuffix = "";
    if (CommonConstant.FileType.IMG.equals(fileType)) {
      fileSuffix = imgSuffix;
    } else if (CommonConstant.FileType.COREIMG.equals(fileType)) {
      fileSuffix = imgSuffix;
    } else if (CommonConstant.FileType.FILE.equals(fileType)) {
      fileSuffix = workSuffix;
    } else if (CommonConstant.FileType.CAD.equals(fileType)) {
      fileSuffix = cadSuffix;
    } else {
      throw new OriginException("88888", "上传文件格式有误");
    }

    boolean fileMatch = false;
    for (MultipartFile f : file) {
      String fileName = f.getOriginalFilename();
      for (String suffix : fileSuffix.split(",")) {
        if (StringUtil.isEmpty(suffix)) {
          continue;
        }
        if (fileName.toLowerCase().indexOf(suffix) >= 0) {
          fileMatch = true;
          break;
        }
      }
      if (!fileMatch) {
        throw new OriginException("88888", "上传文件格式错误");
      }
    }
  }

  /**
   * 验证一次文件上传数量
   *
   * @param file
   * @param fileType
   * @return void
   * @author lituo
   * @date 5:46 PM 2021/12/12
   */
  private void checkFileNumber(List<MultipartFile> file, String fileType) {
    int fileSize = file.size();
    if (CommonConstant.FileType.IMG.equals(fileType)) {
      if (fileSize > Integer.valueOf(imgMaxNum)) {
        throw new OriginException("88888", "一次最多上传" + imgMaxNum + "张图片");
      }
    } else if (CommonConstant.FileType.COREIMG.equals(fileType)) {
      if (fileSize > Integer.valueOf(imgMaxNum)) {
        throw new OriginException("88888", "一次最多上传" + imgMaxNum + "张图片");
      }
    } else if (CommonConstant.FileType.FILE.equals(fileType)) {
      if (fileSize > Integer.valueOf(workMaxNum)) {
        throw new OriginException("88888", "一次最多上传" + workMaxNum + "个文件");
      }
    } else if (CommonConstant.FileType.CAD.equals(fileType)) {
      if (fileSize > Integer.valueOf(cadMaxNum)) {
        throw new OriginException("88888", "一次最多上传" + cadMaxNum + "张CAD文件");
      }
    } else {
      throw new OriginException("88888", "上传文件格式有误");
    }
  }

  /**
   * 验证上传文件大小
   *
   * @param file
   * @param fileType
   * @return void
   * @author lituo
   * @date 5:46 PM 2021/12/12
   */
  private void checkFileSize(List<MultipartFile> file, String fileType) {
    String fileSize = "";
    if (CommonConstant.FileType.IMG.equals(fileType)) {
      fileSize = imgMaxSize;
    } else if (CommonConstant.FileType.COREIMG.equals(fileType)) {
      fileSize = imgMaxSize;
    } else if (CommonConstant.FileType.FILE.equals(fileType)) {
      fileSize = workMaxSize;
    } else if (CommonConstant.FileType.CAD.equals(fileType)) {
      fileSize = cadMaxSize;
    } else {
      throw new OriginException("88888", "上传文件格式有误");
    }
    for (MultipartFile f : file) {
      if (!FileUtil.checkFileSize(f.getSize(), Integer.parseInt(fileSize), "M")) {
        throw new OriginException("88888", "上传文件不能超过" + fileSize + "MB");
      }
    }
  }


  /**
   * 自动调节精度(经验数值)
   *
   * @param size 源图片大小
   * @return 图片压缩质量比
   */
  private static double getAccuracy(long size) {
    double accuracy;
    if (size < NINE_ZERO_ZERO) {
      accuracy = ZERO_EIGHT_FIVE;
    } else if (size < TWO_ZERO_FOUR_SEVEN) {
      accuracy = ZERO_SIX;
    } else if (size < THREE_TWO_SEVEN_FIVE) {
      accuracy = ZERO_FOUR_FOUR;
    } else {
      accuracy = ZERO_FOUR;
    }
    return accuracy;
  }


}
